/*
 * @Author: mengqingchen mengqingchen@huaru.cc
 * @Date: 2022-09-07 09:57:45
 * @LastEditors: mengqingchen mengqc1995@163.com
 * @LastEditTime: 2022-12-07 16:42:33
 * @FilePath: \huaru-platform\src\utils\encryption.js
 * @Description:
 */
import CryptoJS from 'crypto-js'
import { JSEncrypt } from 'jsencrypt'
import { getDeviceId, randomString } from './deviceOrRequest'

class encryDecObj {
  constructor() {
    this.instance = null
    this.jse = new JSEncrypt()
    this.iv
    this._deviceId
    this._requestId
    this._public_key
    this._key
    this.url
  }
  static getInstance() {
    if (!this.instance) {
      this.instance = new encryDecObj()
    }
    return this.instance
  }
  /**
   * @description: 创建RSA
   * @return RSA对象
   */
  RSAencrypt(data, public_key) {
    this.jse.setPublicKey(public_key)
    return this.jse.encrypt(data)
  }

  /**
   * @description: 创建加密
   * @param {*} value 需要加密的数据
   * @param {*} public_key 公钥
   * @return {*} 返回后端的前端加解密数据
   */
  createEncryption(value, public_key, requestId) {
    // 生成 desc 密钥 key 24位 iv 8位
    let key = randomString(24)
    this.iv = randomString(8)
    let _key = CryptoJS.enc.Utf8.parse(key)
    let _iv = CryptoJS.enc.Utf8.parse(this.iv)

    // des加密请求数据
    let encryptObject = JSON.stringify(value)
    let encryptResult = CryptoJS.TripleDES.encrypt(encryptObject, _key, {
      iv: _iv,
      mode: CryptoJS.mode.CBC,
      padding: CryptoJS.pad.Pkcs7
    }).toString()

    // rsa加密 des密钥 抛出
    let requestKey = this.RSAencrypt(this.iv + key, public_key)
    //然后使用rsa 公钥加密

    let deviceId = getDeviceId()

    let signObject = CryptoJS.MD5(deviceId + requestId + requestKey + encryptResult).toString()
    let sign = this.jse.encrypt(signObject).toString()
    // 临时变量，用于返回数据解密时校验
    this._deviceId = deviceId
    this._requestId = requestId
    this._public_key = public_key
    this._key = key
    return {
      deviceId,
      requestId,
      key: requestKey,
      value: encryptResult,
      sign,
      interfaceVariable: {
        key,
        iv: this.iv
      }
    }
  }

  decrypt(response, deskey) {
    //响应数据体
    let jsonData = { ...response }
    let jsencrypt = new JSEncrypt()
    jsencrypt.setPublicKey(this._public_key)
    let md5 = CryptoJS.MD5(jsonData.deviceId + jsonData.requestId + jsonData.result).toString()
    //验签
    let verifyed = jsencrypt.verify(md5, jsonData.sign, CryptoJS.SHA1)
    if (verifyed) {
      // des 解密响应数据
      let _key2 = CryptoJS.enc.Utf8.parse(deskey.key)
      let _iv = CryptoJS.enc.Utf8.parse(deskey.iv)

      let result = CryptoJS.enc.Utf8.stringify(
        CryptoJS.TripleDES.decrypt(
          {
            ciphertext: CryptoJS.enc.Base64.parse(jsonData.result),
            iv: '',
            key: '',
            salt: ''
          },
          _key2,
          { iv: _iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }
        )
      )
      if (result.startsWith('{') || result.startsWith('[')) {
        result = JSON.parse(result)
        return result
      }
    } else {
      console.log(1)
      return Promise.reject('解密有误')
    }
  }
}

export default encryDecObj
